#!/usr/bin/perl
#cartprep.pl
#tool to prepare CART training files for WAGON
#database; "boss" as mysql user; "boss" as mysql password; 
#"traindata.txt" as standard output file and output to file as standard output

#version: 1.2
#@autor: Igor Jauk

#Changelist:
#Config class support
#includes preparing data with and without phoxsies
#-h option support
#fixed output file
#minor code improvements

use FindBin qw($Bin);
use lib "$Bin/../libs";
use config;
use DBI;
my @traindata;
my @tkey;
my $USAGE = "perl cartprep.pl -lang LANGUAGE -sp SPEAKERNAME [-phoxsy -user MYSQLUSER -passwd MYSQLPASSWORD -o OUTPUTMODUS -h]";
main();

sub main {
	my $cl = config->new(\@ARGV);
	if ($cl->optionflag("-h")) {
		print $USAGE."\n";
		exit;
	}
	
	
	print "Creating output file traindata.txt\n";
	open OUT, ">traindata.txt" or die "could not create output file traindata.txt\n";

	
	my $dbname;
	my $dbuser;
	my $dbpasswd;
	my $lang;
	my $sp;
	
	#mysql connections
	if ($cl->optionflag("-lang") && $cl->optionflag("-sp")) {
		$lang = $cl->optionarg("-lang");
		$sp = $cl->optionarg("-sp");
		$dbname = "boss_".$lang."_".$sp;
	} else {
		die "Error: no language and no speaker specified. Please specify the language and the speaker corresponding to your database.\n$USAGE\n";
	}
	my $dbdsn = "DBI:mysql:database=$dbname";
	if ($cl->optionflag("-user")) {
		$dbuser = $cl->optionarg("-user");
	} else {
		$dbuser = "boss";
	}
	if ($cl->optionflag("-passwd")) {
		$dbpasswd = $cl->optionarg("-passwd");
	} else {
		$dbpasswd = "boss";
	}

	my $dbh = DBI->connect($dbdsn, $dbuser, $dbpasswd) or die "could not connect to the database\n";
	
	#query, take out the columns and the tablename to an external file!
	my $query = "SELECT Num, First, Last, CLeft, CRight, TKey, Stress from ".$sp."_phone_data";
	
	my $data = $dbh->prepare($query);
	$data->execute();
	my $c = 0;
	
	while (my @ram = $data->fetchrow_array()) {
		$tkey[$c] = $ram[5];
		$c++;
	}
	$c=0;
	my $flag = 1;
	my $oldsyll = 0;
	$data->execute();
	my $buff = '0';
	my $oldsyll;
	while (my @map = $data->fetchrow_array()) {
		my $phx = 0;
		$phx = 1 if $cl->optionflag('-phoxsy');
		my $phrpos = getPhrpos($dbh,$map[0],\$flag, \$oldsyll, $dbname, $sp, $phx);
		my $dur = $map[2]-$map[1];
		my $size = @tkey-2;
		my $cright;
		if ($c<$size) {
		    $cright2 = $tkey[$c+2];
		} else {
		    $cright2 = '$p';
		}
		#format: DUR PLAUT FLAUT FLAUT2 PHRPOS LAUT STRESS
		if ($map[5] eq '$p' && $phrpos eq 'F') {
		    correctPHRPOS($c);
		} elsif ($map[5] eq '$p' && $phrpos eq 'I') {
		    $buff = $phrpos;
		    $oldsyll = checkSyll($map[0]+1, $dbname, $dbh, $sp, $phx);
		} elsif ($map[5] ne '$p' && $buff eq '0') {
		    $traindata[$c] = "$dur $map[3] $map[4] $cright2 $phrpos $map[5] $map[6]";
		    $c++;
		} elsif ($map[5] ne '$p' && $buff eq 'I') {
		    $traindata[$c] = "$dur $map[3] $map[4] $cright2 $buff $map[5] $map[6]";
		    $c++;
		    if (checkSyll($map[0]+1, $dbname, $dbh, $sp, $phx) != $oldsyll) {
		      $buff = '0';
		    }
		}
		$oldnum = $map[0];
		    
	}
	
	$data->finish();
	$dbh->disconnect();
	if ($cl->optionflag("-o")) {
		my $o = $cl->optionarg("-o");
		select $o;
	} else {
		select OUT;
	}
		
	foreach my $e (@traindata) {
		print $e,"\n";
	}
	
	close(OUT);
}

sub getPhrpos {
	my $query = "select PInt FROM ".$_[4].".".$_[5]."_phone_data where Num=$_[1]";
	my $squery = "";
	my $phx = $_[6];
	if ($phx == 1) {
		$squery = "select SyllableNum from ".$_[5]."_syllable_map where ".$_[5]."_syllable_map.PhoxsyNum = ".$_[5]."_phoxsy_map.PhoxsyNum && ".$_[5]."_phoxsy_map.PhoneNum =$_[1]";
	} else {
		$squery = "select SyllableNum from ".$_[5]."_syllable_map where PhoneNum=$_[1]";
	}
	my $pint = $_[0]->prepare($query);
	my $sn = $_[0]->prepare($squery);
	$pint->execute();
	$sn->execute();
	
	my $s = $sn->fetchrow_array();
	
	my $PInt = $pint->fetchrow_array();
	if ($PInt eq "2" or $PInt eq "5") {
		#print "$_[1]  ";
		$$_[2] = 1;
		$$_[3] = $s;
		return("F");
	} elsif (($$_[2]==1 && $PInt ne "2" && $PInt ne "5") || ($$_[2] == 2 && $s eq $$_[3])
	|| $$_[3] == 0) {
		#print $s , "   " , $$_[3] , " I\n";
		#print $$_[2]."\n";
		$$_[2] = 2;
		$$_[3] = $s;
		return("I");
	} else {
		$$_[2] = 0;
		$$_[3] = $s;
		return("M");
	}
	
}

sub correctPHRPOS {
  #$_[0]: $c: current position in the array
	my @buff = split(/ +/,$traindata[$_[0]-1]);
	$buff[4] = 'F';
	$traindata[$_[0]-1] = "";
	for (my $i=0; $i<@buff; $i++) {
		$traindata[$_[0]-1] = $traindata[$_[0]-1].' ' if ($i>0);
		$traindata[$_[0]-1] = $traindata[$_[0]-1].$buff[$i];
	}
}

sub checkSyll {
  #$_[0]: Num, $_[1]: dbname, $_[2]: dbh, $_[3]: speaker, $_[4]: phoxsy flag
	my $phx = $_[4];
	my $query = "";
	if ($phx == 1) {
		$query = "select SyllableNum from ".$_[1].".".$_[3]."_syllable_map where ".$_[3]."_syllable_map.PhoxsyNum = ".$_[3]."_phoxsy_map.PhoxsyNum && ".$_[3]."_phoxsy_map.PhoneNum=$_[0]";
	} else {
		$query = "select SyllableNum from ".$_[1].".".$_[3]."_syllable_map where PhoneNum=$_[0]";
	}
	my $sn = $_[2]->prepare($query);
	$sn->execute();
	my $s = $sn->fetchrow_array();
	return ($s);
}

